<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        /* 一、
            使用工厂方法创建对象：
            步骤：
                1.new一个对象
                2.相应属性和方法赋值
                3.将新建的对象返回
            
            使用工厂方法创建的对象，使用的构造函数都是Object
            所以创建的对象都是Object这个类型，就导致我们无法区分出多种不同类型的对象
        */
        function createPerson(name, age, gender) {
            // 创建一个新的对象
            var obj = new Object();
            // 向对象中添加属性
            obj.name = name;
            obj.age = age;
            obj.gender = gender;
            obj.sayName = function () {
                console.log(this.name);
            }

            // 将新的对象返回
            return obj;
        }

        var obj1 = createPerson("孙悟空", 1000, "男");
        var obj2 = createPerson("猪八戒", 3600, "男");
        var obj3 = createPerson("沙悟净", 10000, "男");

        obj1.sayName();
        obj2.sayName();
        obj3.sayName();

        /* 二、
            构造函数
                构造函数和普通函数区别不大： 
                    普通函数是直接调用
                    构造函数需要使用new关键字来调用；首字母需要大写
                
            
        */

        function Dog() {

        }

        function Person(name, age, gender) {
            //向对象中添加属性
            this.name = name;
            this.age = age;
            this.gender = gender;
            this.sayHello = function () {
                console.log("My'name is " + this.name + ", " +
                    "I'm " + this.age + " years old, " +
                    "and I'm a " + this.gender + ".");
            };
        }

        var person1 = new Person("孙悟空", 1000, "man");
        var person2 = new Person("猪八戒", 3600, "man");
        var person3 = new Person("沙悟净", 10000, "man");
        var dog = new Dog();
        person1.sayHello(); // My'name is 孙悟空, I'm 1000 years old, and I'm a man.
        person2.sayHello(); // My'name is 猪八戒, I'm 3600 years old, and I'm a man.
        person3.sayHello(); // My'name is 沙悟净, I'm 10000 years old, and I'm a man.
        console.log(person1); // Person {name: "孙悟空", age: 1000, gender: "man", sayHello: ƒ}
        console.log(person2); // Person {name: "猪八戒", age: 3600, gender: "man", sayHello: ƒ}
        console.log(person3); // Person {name: "沙悟净", age: 10000, gender: "man", sayHello: ƒ}
        console.log(typeof person1); // object
        console.log(typeof person2); // object
        console.log(typeof person3); // object

        /* 三、
            构造函数进阶1：在全局作用域中定义函数
            因为每个对象都有公共的方法，所以每次new的时候，每个对象的公共方法的内存地址都是不同的，这会占用内存，没必要
     
        */

        function Person(name, age, gender) {
            this.name = name;
            this.age = age;
            this.gender = gender;
            this.sayHello = fun;
        }
        // 将sayName方法在全局作用域中定义
        function fun() {
            console.log("My'name is " + this.name + ", " +
                "I'm " + this.age + " years old, " +
                "and I'm a " + this.gender + ".");
        };

        // 虽然这样节省了内存空间，但却污染了全局作用域的命名空间
        // 而且定义在全局作用域中也很不安全


        /* 四、
            构造函数进阶2：采用原型对象
            在下一节中介绍
        */
    </script>
</head>

<body>

</body>

</html>